/*
 * Copyright (c) 2012 Universidad Antonio de Nebrija.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0
 * which accompanies this distribution, and is available at
 * http://www.apache.org/licenses/LICENSE-2.0.html
 * 
 * Contributors:
 *    Universidad Antonio de Nebrija - initial API, implementation and documentation
 */
package com.nebrija.riif.model.functions;

import java.util.ArrayList;

import com.nebrija.riif.model.Function;
import com.nebrija.riif.model.Util;
import com.nebrija.riif.model.ValueUnit;

/**
 * Function for agg_single_fail
 * @author asanchep
 *
 */
public class AggSingleFailFunction extends Function{

	public static final String NAME="agg_single_fail";
	public static final String MTTF="MTTF";
	public static final String FITS="FITS";
	
	/**
	 * Creates an AggSingleFailFunction object
	 */
	public AggSingleFailFunction() {
		super(AggSingleFailFunction.NAME, -1);
	}

	// TODO: Provide expected return units and units for all operands. 
	// 10^9 is ignored as we suppose that we always return information in the same units
	// as all the operands.
	@Override
	protected Object executeFunction(Object... operands) {
		double result = 0d;
		boolean isMTTF = true;
		StringBuilder notResolved = new StringBuilder();
		for (int i=0; i<operands.length; i++){
			// The resulting object will be an string if any operand is a string
			if (operands[i] instanceof String){
				notResolved.append(",").append(operands[i]);
				continue;
			}else if (operands[i] instanceof ValueUnit){
				// ValueUnit include the unit (FITS/MTTF)
				ValueUnit vu = (ValueUnit) operands[i];
				if(vu.getUnit().equals(FITS)){ // we suppose all the operands in the same units.
					isMTTF=false;
					result+=vu.getValue();
				}else{
					result+=1/vu.getValue();
				}
			} else if (operands[i] instanceof ArrayList<?>){
				// If an arraylist is found, the elements must be retrieved
				@SuppressWarnings("unchecked")
				ArrayList<Object> al = (ArrayList<Object>)operands[i];
				for(int j=0;j<al.size();j++){
					Object op = al.get(j);
					if(op instanceof String){
						notResolved.append(",").append(operands[i]);
						continue;
					}
					if (op instanceof ValueUnit){
						ValueUnit vu = (ValueUnit) op;
						if(vu.getUnit().equals(FITS)){ // we suppose all the operands in the same units and return value expected in those units as well.
							isMTTF=false;
							result+=vu.getValue();
						}else{
							result+=1/vu.getValue();
						}
					}else{
						result+=1/Util.convertToDouble(op); //We suppose units are MTTF
					}
				}
			}else{
				result+=1/Util.convertToDouble(operands[i]); //We suppose units are MTTF
			}
		}
		
		// If units are MTTF we need to get the inverse
		if(isMTTF){
			result=1/result;
		}
		
		// If any operand was a string we will return the concatenation of the result and the not resolved string
		if(notResolved.length()>0){
			return NAME+"("+result+notResolved.toString()+")";
		}
		
		return result;
	}
	
}
